#include "EventLoop.h"
#include "Acceptor.h"
#include "TcpConnection.h"
#include "EventLoopThreadPool.h"
#include <iostream>
#include <memory>
#include <atomic>
#include <map>

class TcpServer
{
public:
    TcpServer(EventLoop *loop, const std::string &ip, uint16_t port, int numThreads)
        : loop_(loop),
          acceptor_(loop, ip, port),
          threadPool_(loop, numThreads),
          connectionCount_(0)
    {

        acceptor_.setNewConnectionCallback(std::bind(
            &TcpServer::newConnection, this,
            std::placeholders::_1, std::placeholders::_2
        ));
    }

    void start()
    {
        threadPool_.start();
        acceptor_.listen();
        std::cout << "TcpServer 启动，是否已监听：" << acceptor_.listenning() << std::endl;
    }

private:
    void newConnection(int sockfd, const sockaddr_in &peerAddr)
    {
        char buf[64];
        snprintf(buf, sizeof(buf), "conn-%d", ++connectionCount_);
        std::string connName = buf;

        EventLoop *ioLoop = threadPool_.getNextLoop();

        sockaddr_in localAddr;
        socklen_t addrLen = sizeof(localAddr);
        getsockname(sockfd, (sockaddr *) &localAddr, &addrLen);

        TcpConnection::Pointer conn = std::make_shared<TcpConnection>(
            ioLoop, sockfd, localAddr, peerAddr);
        conn->setMessageCallback(std::bind(
            &TcpServer::onMessage, this,
            std::placeholders::_1, std::placeholders::_2
        ));
        conn->setCloseCallback(std::bind(
            &TcpServer::onClose, this,
            std::placeholders::_1
        ));

        connections_[connName] = conn;
        ioLoop->runInLoop(std::bind(&TcpConnection::connectEstablished, conn));

        std::cout << "新连接建立：" << connName << std::endl;
    }

    void onMessage(const TcpConnection::Pointer &conn, const std::string &message)
    {
        std::cout << "收到来自 " << conn->name() << " 的数据：" << message << std::endl;
        conn->send("Echo: " + message);
    }

    void onClose(const TcpConnection::Pointer &conn)
    {
        std::cout << "连接关闭：" << conn->name() << std::endl;
        connections_.erase(conn->name());
    }

    EventLoop *loop_;
    Acceptor acceptor_;
    EventLoopThreadPool threadPool_;
    std::atomic<int> connectionCount_;
    std::map<std::string, TcpConnection::Pointer> connections_;
};

int main()
{
    EventLoop loop;
    TcpServer server(&loop, "192.168.127.130", 8080, 4);
    server.start();
    loop.loop();
    return 0;
}